/*******************************************************************************
 * FilePath    : \Software\Examples\Ble\ble_app_peripheral_uart\Src\BSP\BSP.c
 * Version     : 1.0
 * Brief       : 
 * Author      : AndrewHu
 * Company     : Shanghai MacroGiga Electronics CO.,Ltd
 * Email       : Hubinbo@macrogiga.com
 * Date        : 2020-04-03 15:06:14
 * LastEditors : AndrewHu
 * LastEditTime: 2021-04-21 18:10:49
 * Description : 
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <Includes.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//运行模式，00-normal，01-sleep;02-stop(ble),03-standby
static u8 RunningMode = RunningMode_Normal;
// static u8 RunningMode = RunningMode_Sleep;
static u8 RunningStatus = 0;      //当前运行状态
static u8 RadioStandbyStatus = 0; //蓝牙射频进入低功耗状态标记
static u8 EnterSleepDelay = 0x00; //进入低功耗延时
static u8 SleepStatus = 0x00;
/* Private function ----------------------------------------------------------*/
/* extern --------------------------------------------------------------------*/

/*******************************************************************************
 * Function    : 
 * Brief       : 运行模式操作
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-06 00:41:31
 * Description : 
 ******************************************************************************/
u8 getRunningMode(void)
{
    return RunningMode;
}
u8 getRunningStatus(void)
{
    return SleepStatus;
}
void SetRunningMode(u8 mode)
{
    RunningMode = mode;
}
/*******************************************************************************
 * Function    : ClearEnterSleepDelay
 * Brief       : 延时进入休眠
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-17 13:28:22
 * Description : 
 ******************************************************************************/
void ClearEnterSleepDelay(void)
{
    EnterSleepDelay = 0x00;
}
/*******************************************************************************
 * Function    : SystemClk_HSIInit
 * Brief       : 系统时钟初始化函数，初始化之前先复位所有时钟
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 15:29:16
 * Description : 
 ******************************************************************************/
void SystemClk_HSIInit(void)
{
    //HSI=48M
    unsigned char temp = 0;

    RCC->CR |= RCC_CR_HSION;
    while (!(RCC->CR & RCC_CR_HSIRDY))
        ;

    RCC->CR &= ~(1 << 20);
    RCC->CR &= ~(1 << 2);
    RCC->CFGR = RCC_CFGR_PPRE1_1;
    FLASH->ACR = FLASH_ACR_LATENCY_1 | FLASH_ACR_PRFTBE;
    RCC->CFGR &= ~RCC_CFGR_SW;
    RCC->CFGR |= 0x02;
    while (temp != 0x02)
    {
        temp = RCC->CFGR >> 2;
        temp &= 0x03;
    }
}
/*******************************************************************************
 * Function    : IRQ_Init
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 16:59:42
 * Description : 
 ******************************************************************************/
void IRQ_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    //IRQ - PA12
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    SYSCFG_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource12);
    EXTI_InitStructure.EXTI_Line = EXTI_Line12;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_SetPriority(EXTI4_15_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
}
/*******************************************************************************
 * Function    : GPIO_Init_Else
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2021-04-21 13:58:38
 * Description : 
 ******************************************************************************/
void GPIO_Init_Else(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*******************************************************************************
 * Function    : BSP_Init
 * Brief       : 硬件（IO）初始化
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 15:56:40
 * Description : 
 ******************************************************************************/
void BSP_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    SystemClk_HSIInit();   //系统时钟设定
    SysTick_Config(48000); //48M，滴答时钟1ms计时

    Flash_Read();
    //SPIM_Init(0x06); //8Mhz
    SPIM_Init(0x08); //6Mhz
    IRQ_Init();      //Irq中断设置

    //串口设置
    UartInit(GetBaudRate());
    //ChangeBaudRate(GetBaudRate());

    Led_Init();
    Key_Init();
    GPIO_Init_Else();

    Write_Iwdg_ON(IWDG_Prescaler_256, 5000); //6.4s, fff-26.208s max
}
/*******************************************************************************
 * Function    : Mcu_Sleep
 * Brief       : 芯片MCU部分进入低功耗
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-17 13:52:12
 * Description : 
 ******************************************************************************/
void Mcu_Sleep(void)
{
    if (SleepStatus == 0x00)
    {
        Uart2Exit();        //串口唤醒使能
        SleepStatus = 0x01; //完成低功耗设置
    }

    //休眠指令
    SCB->SCR |= 0x4;
    __WFI();
}
/*******************************************************************************
 * Function    : Mcu_WakeUp
 * Brief       : 芯片退出低功耗
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-06-23 15:42:08
 * Description : 
 ******************************************************************************/
void Mcu_WakeUp(u8 status)
{
    if (status == 0x01)
    {
        //外设唤醒
        if (SleepStatus == 0x00)
            return;             //非低功耗模式，不重复设定
        Exit2Uart();            //串口退出低功耗
        SleepStatus = 0x00;     //确认退出低功耗
        ClearEnterSleepDelay(); //进入低功耗延时
        RunningMode = RunningMode_Normal;
        Printf_Wakeup();
    }
}
/*******************************************************************************
 * Function    : RadioStandby
 * Brief       : 蓝牙射频端工作状态
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-17 13:56:49
 * Description : 
 ******************************************************************************/
static void RadioStandby(u8 status)
{
    if (RadioStandbyStatus)
    {
        //目前处于休眠状态
        if (status == 0)
        {
            RCC_LSICmd(ENABLE); //in STANDBY iwdg will cause reset
            radio_resume();     //唤醒蓝牙
        }
    }
    else
    {
        //目前处于工作状态
        if (status)
        {
            RCC_LSICmd(DISABLE); //in STANDBY iwdg will cause reset
            radio_standby();     //关闭蓝牙功能
        }
    }
    RadioStandbyStatus = status; //保存工作状态
}
/*******************************************************************************
 * Function    : IrqMcuGotoSleepAndWakeup
 * Brief       : Following functions are porting functions
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 15:58:39
 * Description : 
 ******************************************************************************/
void IrqMcuGotoSleepAndWakeup(void) // auto goto sleep AND wakeup, porting api
{
    if ((RunningStatus != RunningMode_Stop) && (RunningStatus != RunningMode_Standby))
    {
        //蓝牙射频没有关闭，需要判断是否可以进入休眠接口
        if (ble_run_interrupt_McuCanSleep() == 0)
        {
            //蓝牙不能进入休眠，EnterSleepDelay清零
            ClearEnterSleepDelay();
            return;
        }
    }

    //进入低功耗延时，当EnterSleepDelay清零时开始累计次数
    if (GetUartStatus() != 0)
    {
        //串口有数据待处理或按键按下，不能进入休眠
        ClearEnterSleepDelay();
        return;
    }
    else if (EnterSleepDelay < 0xf0)
    {
        EnterSleepDelay++;
        return;
    }
    //可以进入休眠，休眠模式判断
    switch (RunningMode)
    {
    case RunningMode_Normal:
        /* Normal ------------------------------------------------------------*/
        RadioStandby(0); //射频工作
        RunningStatus = RunningMode_Normal;
        break;
    case RunningMode_Sleep:
        /* Sleep -------------------------------------------------------------*/
        RadioStandby(0); //蓝牙射频工作
        RunningStatus = RunningMode_Sleep;
        Mcu_Sleep(); //MCU部分进入休眠
        break;
    case RunningMode_Stop:
        /* Stop --------------------------------------------------------------*/
        //省电，蓝牙停止，仅MCU运行，(功耗比sleep大)
        if (GetConnectedStatus())
        {
            ble_disconnect(); //连接状态，先断开蓝牙
            return;
        }

        RadioStandby(1); //蓝牙射频不工作
                         //设定看门狗唤醒和串口唤醒功能
        RunningStatus = RunningMode_Stop;
        IWDG_ReloadCounter();
        break;
    case RunningMode_Standby:
        /* Standby -----------------------------------------------------------*/
        //整个系统进入休眠(功耗最低)
        if (GetConnectedStatus())
        {
            ble_disconnect(); //连接状态，先断开蓝牙
            return;
        }

        RadioStandby(1); //蓝牙射频不工作
        LED_OnOff(0);    //关闭指示灯
        RunningStatus = RunningMode_Standby;
        Mcu_Sleep(); //MCU部分进入休眠
        break;
    default:
        /* Else --------------------------------------------------------------*/
        //默认省电模式
        RunningMode = RunningMode_Sleep;
        RunningStatus = RunningMode_Sleep;
        RadioStandby(0); //蓝牙射频工作
        break;
    }
}
/*******************************************************************************
 * Function    : 
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 15:58:17
 * Description : DO NOT REMOVE, used in ble lib
 ******************************************************************************/
void McuGotoSleepAndWakeup(void)
{
}
void SysClk8to48(void)
{
}
void SysClk48to8(void)
{
}
static char dis_int_count = 0;
void DisableEnvINT(void)
{
    __ASM volatile("cpsid i");
    dis_int_count++;
}
void EnableEnvINT(void)
{
    //to enable/recover int
    dis_int_count--;
    if (dis_int_count <= 0) //protection purpose
    {
        dis_int_count = 0; //reset
        __ASM volatile("cpsie i");
    }
}
void UpdateLEDValueAll(void)
{
}
unsigned char aes_encrypt_HW(unsigned char *_data, unsigned char *_key)
{
    return 0;
}
